﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.IO;
using System.Reflection;

namespace WPFExcelReport.Helpers
{
    public class TextFileReader : IEnumerable<string[]>
    {
        private string _fileName = string.Empty;
        private string _delimiter = string.Empty;

        public TextFileReader(string fileName, string delimiter)
        {
            this._fileName = fileName;
            this._delimiter = delimiter;
        }

        #region IEnumerable<string[]> Members

        IEnumerator<string[]> IEnumerable<string[]>.GetEnumerator()
        {//.GetEncoding("GB2312")
            using (StreamReader streamReader = new StreamReader(this._fileName, System.Text.Encoding.GetEncoding("utf-8")))
            {
                while (!streamReader.EndOfStream)
                {
                    yield return streamReader.ReadLine().Split(new char[] { ',' });
                }
            }
        }

        #endregion

        #region IEnumerable Members

        IEnumerator IEnumerable.GetEnumerator()
        {
            return ((IEnumerable)((IEnumerator<string[]>)this)).GetEnumerator();
        }

        #endregion
    }

    public class TextFileReader<T> : IEnumerable<T> where T : new()
    {
        private string _fileName = string.Empty;
        private string _delimiter = string.Empty;
        private Dictionary<String, PropertyInfo> _headerPropertyInfos = new Dictionary<string, PropertyInfo>();
        private Dictionary<String, Type> _headerDaytaTypes = new Dictionary<string, Type>();

        public TextFileReader(string fileName, string delimiter)
        {
            this._fileName = fileName;
            this._delimiter = delimiter;
        }

        #region IEnumerable<string[]> Members

        IEnumerator<T> IEnumerable<T>.GetEnumerator()
        {
            using (StreamReader streamReader = new StreamReader(this._fileName, System.Text.Encoding.Default))
            {
                string[] headers = streamReader.ReadLine().Split(new String[] { this._delimiter }, StringSplitOptions.None);
                this.ReadHeader(headers);
                
                while (!streamReader.EndOfStream)
                {
                    T item = new T();

                    string[] rowData = streamReader.ReadLine().Split(new String[] { this._delimiter }, StringSplitOptions.None);

                    for (int index = 0; index < headers.Length; index++)
                    {
                        string header = headers[index];
                        this._headerPropertyInfos[header].SetValue(item, Convert.ChangeType(rowData[index], this._headerDaytaTypes[header]), null);
                    }
                    yield return item;
                }
            }
        }

        #endregion

        #region IEnumerable Members

        IEnumerator IEnumerable.GetEnumerator()
        {
            return ((IEnumerable)((IEnumerator<T>)this)).GetEnumerator();
        }

        #endregion

        private void ReadHeader(string[] headers)
        {
            foreach (String header in headers)
            {
                foreach (PropertyInfo propertyInfo in (typeof(T)).GetProperties())
                {
                    foreach (object attribute in propertyInfo.GetCustomAttributes(true))
                    {
                        if ( attribute is ColumnAttribute )
                        {
                            ColumnAttribute columnAttribute = attribute as ColumnAttribute;
                            if (columnAttribute.Name == header)
                            {
                                this._headerPropertyInfos[header] = propertyInfo;
                                this._headerDaytaTypes[header] = columnAttribute.DataType;
                                break;
                            }
                        }
                    }
                }
            }
        }
    }
}